﻿
Public Class Grammar
    Private s_lastMaxTerminalIndex As Integer = 0
    Private s_lastMaxNonTerminalIndex As Integer = 0
    Private s_lastMaxProductionIndex As Integer = 0

    Private m_nonTerminals As Dictionary(Of Integer, NonTerminal)
    Private m_terminals As Dictionary(Of Integer, Terminal)
    Private m_productions As Dictionary(Of Integer, Production)

    Public Function AddTerminal(ByVal id As Integer) As Terminal
        If m_terminals.ContainsKey(id) Then
            Contract.GeneralArgumentError("id", "The terminal id has been already assigned to another terminal")
        End If

        Dim newTerminal As New Terminal(id)
        If id > s_lastMaxTerminalIndex Then

            'lock
            s_lastMaxTerminalIndex = id
        End If

        m_terminals.Add(id, newTerminal)

        Return newTerminal
    End Function

    Public Function GetTerminal(ByVal id As Integer) As Terminal
        Contract.AssertArgumentInRange(m_terminals.ContainsKey(id), "id", "The terminal id is not exist in this grammar")

        Return m_terminals(id)
    End Function

    Public Function AddTerminal() As Terminal
        Return AddTerminal(s_lastMaxTerminalIndex + 1)
    End Function

    Public Function AddNonTerminal(ByVal id As Integer) As NonTerminal
        If m_nonTerminals.ContainsKey(id) Then
            Contract.GeneralArgumentError("id", "The terminal id has been already assigned to another terminal")
        End If

        Dim newNonTerminal As New NonTerminal(id, Me)
        If id > s_lastMaxTerminalIndex Then

            'lock
            s_lastMaxTerminalIndex = id
        End If
        m_nonTerminals.Add(id, newNonTerminal)

        Return newNonTerminal
    End Function

    Public Function GetNonTerminal(ByVal id As Integer) As NonTerminal
        Contract.AssertArgumentInRange(m_terminals.ContainsKey(id), "id", "The terminal id is not exist in this grammar")

        Return m_nonTerminals(id)
    End Function

    Public Function AddNoneTerminal() As NonTerminal
        Return AddNonTerminal(s_lastMaxTerminalIndex + 1)
    End Function

    Public Sub AddProduction(ByVal p As Production)

    End Sub
End Class
